require 'event_editor/command_panel'
require 'event_editor/character_select_dialog'
require 'event_editor/commands/condition'
require 'event_editor/commands/route'
require 'event_editor/io'
require 'event_editor/commands/condition'
require 'gadgets/combobox'
require 'gadgets/listbox'

module EventEditor
  class EventDialog

     IMG_BOX_WIDTH = 128
     IMG_BOX_HEIGHT = 128
     ZOOM = 4
     
     LAYER_MODEL = [['1:Bottom', 0], ['2:Top', 1], ['3:Over', 2]]
     SPEED_MODEL = [['1:Slowest', 0], ['2:Slower', 1], ['3:Normal', 2], ['4:Faster', 3], ['5:Fastest', 4]]
     TRIGGER_MODEL = [['Checked', 'checked'], ['Touched', 'touched'], ['Touch', 'touch'], ['Auto', 'auto'], ['Parallel', 'parallel'], ['Never', 'never']]
     
     @dialog = nil
     
     def self.show(base, model, &func)
        @init = false
        @model = model
        
        @deleting = false
        back_up = Marshal.dump(@model.selected_event['pages'])
        
        @model.selected_page_no = -1
        event = model.selected_event

        self.create_dialog(base, "") unless @dialog

        self.load(event)
        @dialog.vbox.show_all
        
        response = @dialog.run
        if response == Gtk::Dialog::RESPONSE_OK
          self.save
          func.call(event)
        else
          @model.events[@model.selected_event_no]['pages'] = Marshal.load(back_up)
        end
        #@dialog.hide
        @dialog.destroy
        @dialog = nil
      end
      
      def self.set_signals
        @trigger_combobox.signal_connect('changed') do
          case @trigger_combobox.selected_data
          when 'checked', 'touched', 'touch'
            @event_combobox.sensitive = true
          else
            @event_combobox.sensitive = false
          end
        end
        
        
        @page_box.signal_connect('button-press-event') do
          self.save_page
          nil
        end
      
        @page_box.signal_connect("switch-page") do |obj, page, page_num|
          self.load_page(page_num) unless @deleting
        end
      end
      
      def self.create_dialog(base, no)
        @dialog = Gtk::Dialog.new("Event#{no}",
               base,
               Gtk::Dialog::MODAL |
               Gtk::Dialog::DESTROY_WITH_PARENT,
               ["OK", Gtk::Dialog::RESPONSE_OK],
               ["Cancel", Gtk::Dialog::RESPONSE_CANCEL]
               )

        tool_bar = EventDialog.create_toolbar
        @page_box = Gtk::Notebook.new
        @image_box_texture = Texture.new(IMG_BOX_WIDTH, IMG_BOX_HEIGHT)
                
        @dialog.vbox.pack_start(tool_bar, false ,false)
                
        @dialog.vbox.pack_start(@page_box, false, false)
        @dialog.vbox.add(EventDialog.create_page)
        self.set_signals
      end

      def self.create_page
        hbox = Gtk::HBox.new
        hbox.set_size_request(800, 550)

        @status_panel = self.create_status_panel
        @status_panel.set_width_request(300)
        
        @command_panel = CommandPanel.new(@dialog, @model)
        hbox.pack_start(@status_panel, false, false)
        hbox.add(@command_panel)
        
        return hbox
      end
      
      def self.create_conditions_panel
        frame = Gtk::Frame.new('conditions')
        
        box = Gtk::HBox.new
        box.set_border_width(5)
        box.pack_start(self.create_condition_panel, true, true)
        
        #box.pack_start(self.create_condition_panel('Trigger'), true, true)
        box.set_height_request(150)
        frame.add(box)
        return frame
      end
      
      def self.create_condition_panel
        @menu = Gtk::Menu.new
        items = {}
        
        t = Gtk::MenuItem.new("add")
        t.signal_connect('activate') do

        end
        @menu.append(t)
        @menu.show_all
    
        box = Gtk::VBox.new
        box.set_border_width(5)
        @condition_listbox = ::Gadgets::Listbox.new("Condition", [String, Array], {:selection_mode => Gtk::SELECTION_MULTIPLE})

        @condition_listbox.signal_connect("button-press-event") do |item, event|
          if event.button  == 3
           self.show_condition_dialog
           #@menu.popup(nil, nil, event.button, event.time)
          end 
        end
        @condition_listbox.signal_connect('key-press-event') do |widget, event|
          if event.keyval == 65535
            @condition_listbox.delete_selected_items
          end
        end
        return @condition_listbox
      end
      
      def self.create_hit_area_panel
        hbox = Gtk::HBox.new
        
        frame = Gtk::Frame.new("Hit Area")
        box = Gtk::HBox.new
        frame.add(box)
        
        # Map X Input
        @hit_x_input = Gtk::SpinButton.new(1, 99, 1)
        @hit_x_input.width_request = 30
        @hit_x_input.value = 1
        box.add(@hit_x_input)
        
        box.add(Gtk::Label.new(' x ', true))
        
        @hit_y_input = Gtk::SpinButton.new(1, 99, 1)
        @hit_y_input.width_request = 30
        @hit_y_input.value = 1
        box.add(@hit_y_input)
        hbox.add(frame)
        
        frame = Gtk::Frame.new("Off set")
        box = Gtk::HBox.new
        frame.add(box)
        
        # Offset X Input
        @offset_x_input = Gtk::SpinButton.new(-99, 99, 1)
        @offset_x_input.width_request = 30
        @offset_x_input.value = 0
        box.add(@offset_x_input)
        
        box.add(Gtk::Label.new(' x ', true))
        
        @offset_y_input = Gtk::SpinButton.new(-99, 99, 1)
        @offset_y_input.width_request = 30
        @offset_y_input.value = 0
        box.add(@offset_y_input)
        hbox.add(frame)
        
        return hbox
      end
      
      def self.show_condition_dialog
        Commands::Condition.show(@dialog, @model, [], :static => true) do |command|
          @condition_listbox.add_item(Commands::Condition.command_to_s(@model, command), command)
        end
      end
            
      def self.create_trigger_panel
        frame = Gtk::Frame.new('Trigger')
        
        @trigger_combobox = ::Gadgets::Combobox.new(TRIGGER_MODEL, [String, String])
        
        @event_combobox = ::Gadgets::Combobox.new(@model.event_select_list(:others), [String, Integer])
        @event_combobox.sensitive = false
        hbox = Gtk::HBox.new(false, 5)
        hbox.add(@trigger_combobox)
        hbox.add(@event_combobox)
        frame.add(hbox)
        return frame
      end
      
      def self.create_status_panel
        box = Gtk::VBox.new
        
        box.pack_start(self.create_conditions_panel, false, false)
        box.pack_start(self.create_hit_area_panel, false, false)
        
        hbox = Gtk::HBox.new
        hbox.pack_start(self.create_graphic_panel, false, false, 10)
        hbox.add(self.create_move_panel)
        
        box.pack_start(hbox, false, false)
        
        box.add(create_trigger_panel)
        box.add(self.create_option_panel)
        box.set_width_request(300)
        return box
      end
      
      def self.get_label_box(name, width)
        l = Gtk::Label.new(name)
        l.set_xalign(0)
        l.set_width_request(50)
        return l
      end
      
      def self.create_move_panel
        frame = Gtk::Frame.new('Movement')
        frame.set_border_width(4)
        vbox = Gtk::VBox.new(true, 0)
        box = Gtk::HBox.new
        
        label_width = 50
        box_width = 100

        # Speed Combo Box
        box = Gtk::HBox.new

        @speed_combobox = ::Gadgets::Combobox.new(SPEED_MODEL, [String, Integer])
        @speed_combobox.set_width_request(box_width)
        box.add(self.get_label_box('Speed', label_width))
        box.add(@speed_combobox)
        vbox.add(box)

        # Wait Input Box
        box = Gtk::HBox.new
        @move_wait_input = Gtk::SpinButton.new(0, 99, 1)
        box.add(self.get_label_box('Wait', label_width))
        box.add(@move_wait_input)
        @move_wait_input.set_width_request(box_width)
        vbox.add(box)

        # Layer Combo Box
        box = Gtk::HBox.new
        @layer_combobox = ::Gadgets::Combobox.new(LAYER_MODEL, [String, Integer])
        @layer_combobox.set_width_request(box_width)
        box.add(self.get_label_box('Layer', label_width))
        box.add(@layer_combobox)
        vbox.add(box)

        # Type Combo Box
        # arr = ['Fixed']
        # arr += IO.get_move_command_names
        # @move_type_combobox = Gtk::Combo.new(arr)
        # @move_type_combobox.entry.set_editable(false)
        # @move_type_combobox.set_width_request(box_width)
        # box.add(self.get_label_box('Type', label_width))
        # box.add(@move_type_combobox)
        # vbox.add(box)
        
        route_button = Gtk::Button.new('Route')
        route_button.signal_connect('clicked') do
          Commands::Route.show(@dialog, @model, [], {:static => true}) do |route, route_skip, route_repeat|
            @model.selected_event_page['route'] = route
            @model.selected_event_page['status']['route_skip'] = route_skip
            @model.selected_event_page['status']['route_repeat'] = route_repeat
          end
        end
        vbox.add(route_button)
        
        frame.add(vbox)
        return frame
      end
            
      def self.create_graphic_panel
        
        vbox = Gtk::VBox.new
        vbox.pack_start(Gtk::Label.new('Graphic'), false ,false)
        vbox.add(@graphic_box = self.create_graphic_box)
        return vbox
      end

      def self.create_graphic_box
        drawing_area = Gtk::DrawingArea.new
        
        drawing_area.signal_connect('expose_event') do
          self.refresh
        end
        set_background_image("res/tex.png", drawing_area)
        drawing_area.set_size_request(IMG_BOX_WIDTH, IMG_BOX_HEIGHT)

        drawing_area.add_events(Gdk::Event::BUTTON_PRESS_MASK)

        drawing_area.signal_connect('button-press-event') do |item, event|
          if event.button  == 1
            status = @model.selected_event_page['status']
            CharacterSelectDialog.show(@dialog, @model, status['chip_id'], status['frame_no'].to_i, status['dir'].to_i) do |chip_id, frame_no, dir|
              @model.selected_event_page['status']['chip_id'] = chip_id
              @model.selected_event_page['status']['dir'] = dir
              @model.selected_event_page['status']['frame_no'] = frame_no
              self.refresh_source_texture
              self.refresh
            end
          end
        end
        return drawing_area
      end

      def self.create_option_panel
        frame = Gtk::Frame.new('Options')
        frame.set_border_width(4)
        hbox = Gtk::HBox.new
        
        # left part
        vbox = Gtk::VBox.new
        vbox.add(@dir_fix = Gtk::CheckButton.new('Direction fixed'))
        vbox.add(@move_anime = Gtk::CheckButton.new('anime(move)'))
        vbox.add(@stay_anime = Gtk::CheckButton.new('anime(stay)'))
        hbox.add(vbox)
        
        # right part
        vbox = Gtk::VBox.new
        vbox.add(@pass_tile = Gtk::CheckButton.new('Pass(tile)'))
        vbox.add(@pass_character = Gtk::CheckButton.new('Pass(character)'))
        vbox.add(@pass_event = Gtk::CheckButton.new('Pass(event)'))
        hbox.add(vbox)
        
        frame.add(hbox)
        return frame
      end
      
      def self.add_tab
        page = Gtk::HBox.new
        page.set_height_request(1)
        @page_box.append_page(page, Gtk::Label.new(@model.selected_event['pages'].length.to_s))
        @page_box.show_all
      end
      
      def self.create_toolbar
        @name_input = Gtk::Entry.new
        toolbar = Gtk::Toolbar.new
        toolbar.append(@name_input)
        
        add_tool_button(toolbar, "New", "icon/new.xpm") do
          @model.selected_event['pages'] << @model.generate_event_page
          self.add_tab
        end

        add_tool_button(toolbar, "Delete", "icon/delete.xpm") do
          len = @model.selected_event['pages'].length
          if len > 1
            @model.selected_event['pages'].delete_at(@model.selected_page_no)
            @deleting = true
            page_no = [@model.selected_page_no, len - 2].min
            self.load_page(page_no)
            @page_box.remove_page(len - 1)
            @page_box.page = page_no
            @deleting = false
          end
        end

        add_tool_button(toolbar, "Copy", "icon/copy.xpm") do
          $buffer['event_page'] = Marshal.dump(@model.selected_event_page)
        end
        add_tool_button(toolbar, "Paste", "icon/paste.xpm") do
          if $buffer['event_page']
            if @model.selected_page_no >= @model.selected_event['pages'].length - 1
              @model.selected_event['pages'].insert(@model.selected_page_no + 1, Marshal.load($buffer['event_page']))
            else
              @model.selected_event['pages'] << Marshal.load($buffer['event_page'])
            end
            self.add_tab
          end
        end
        toolbar.append_space    

        return toolbar
      end
      
      def self.load(event)
        @event = event
        @dialog.title = "Event#{event['id']}"
        @name_input.text = event['name']
        
        @page_box.children.each do |child|
          @page_box.remove(child)
        end
      
        event['pages'].length.times do |i|
          page = Gtk::HBox.new
          page.set_height_request(1)
          @page_box.append_page(page, Gtk::Label.new((i + 1).to_s))
        end
        self.load_page(0)
      end

      def self.load_page(page_no)
        @model.selected_page_no = page_no
        # load status
        @speed_combobox.select(@model.selected_event_page['status']['speed'])
        
        # load hit area
        t = @model.selected_event_page['status']['hit_x']
        @hit_x_input.value = t ? t : 1
        t = @model.selected_event_page['status']['hit_y']
        @hit_y_input.value = t ? t : 1
        
        t = @model.selected_event_page['status']['off_x']
        @offset_x_input.value = t ? t : 0
        t = @model.selected_event_page['status']['off_y']
        @offset_y_input.value  = t ? t : 0
        
        # wait input
        t = @model.selected_event_page['status']['wait'].to_i
        @move_wait_input.value = t
        
        # speed combo
        @layer_combobox.select(@model.selected_event_page['status']['layer'])
        
        # Trigger
        @trigger_combobox.select(@model.selected_event_page['triggers'][0][0])
        @event_combobox.select(@model.selected_event_page['triggers'][0][1])
        # load options
        # direction fix
        @dir_fix.active = @model.selected_event_page['options']['dir_fix']
        @move_anime.active = @model.selected_event_page['options']['move_anime']
        @stay_anime.active = @model.selected_event_page['options']['stay_anime']
        @pass_character.active = @model.selected_event_page['options']['pass_character']
        @pass_event.active = @model.selected_event_page['options']['pass_event']
        @pass_tile.active = @model.selected_event_page['options']['pass_tile']
       
        
        # load list box
        @condition_listbox.clear
        @model.selected_event_page['conditions'].each do |commands|
          @condition_listbox.add_item(Commands::Condition.command_to_s(@model, commands), commands)
        end
        
        # load commands
        @command_panel.load(@model.selected_event_page['commands']) if @init
        
        self.refresh_source_texture
        self.refresh if @graphic_box.window
      end
      
      def self.save
        @event['name'] = @name_input.text
        self.save_page
      end
      
      def self.save_page
        # save status
        @model.selected_event_page['status']['speed'] = @speed_combobox.selected_data
        @model.selected_event_page['status']['layer'] = @layer_combobox.selected_data
        @model.selected_event_page['status']['wait'] = @move_wait_input.value.floor
        
        @model.selected_event_page['status']['hit_x'] = @hit_x_input.value.floor
        @model.selected_event_page['status']['hit_y'] = @hit_y_input.value .floor
        @model.selected_event_page['status']['off_x'] = @offset_x_input.value.floor
        @model.selected_event_page['status']['off_y'] = @offset_y_input.value .floor
        
        @model.selected_event_page['triggers'][0] = [@trigger_combobox.selected_data, @event_combobox.selected_data]

        # save options
        @model.selected_event_page['options']['dir_fix'] = @dir_fix.active?
        @model.selected_event_page['options']['move_anime'] = @move_anime.active?
        @model.selected_event_page['options']['stay_anime'] = @stay_anime.active?
        @model.selected_event_page['options']['pass_character'] = @pass_character.active?
        @model.selected_event_page['options']['pass_event'] = @pass_event.active?
        @model.selected_event_page['options']['pass_tile'] = @pass_tile.active?

        arr = []
        @condition_listbox.each do |item|
          arr << item[1]
        end
        @model.selected_event_page['conditions'] = arr
        @model.selected_event_page['commands'] = @command_panel.commands
      end
      
      def self.refresh_source_texture
        if @model.selected_event_page['status']['chip_id']
          @source_texture = Texture.load($res.image_path + "game/character/" + @model.selected_event_page['status']['chip_id'])
        else
          @source_texture = nil
        end
      end
      
      def self.refresh
        id = @model.selected_event_page['status']['chip_id']
        
        if id
          chara_width = @model.character_chipsets_setting[id]['gw']
          chara_height = @model.character_chipsets_setting[id]['gh']
        end
        
        # Refresh Command List
        @command_panel.load(@model.selected_event_page['commands']) unless @init
        @init = true
        # Refresh Graphic
        @graphic_box.window.clear
        if @source_texture
          tw = chara_width * ZOOM
          th = chara_height * ZOOM

          texture = @image_box_texture
          texture.fill(Color.new(155, 255, 255, 255))
          
          tx = [0, (texture.width - chara_width * ZOOM) / 2].max
          ty = [0, (texture.height - chara_height * ZOOM) / 2].max
          texture.render_texture(@source_texture, tx, ty, 
          :src_x => chara_width * @model.selected_event_page['status']['frame_no'].to_i, 
          :src_y => chara_height * @model.selected_event_page['status']['dir'].to_i,
          :src_width => chara_width,
          :src_height => chara_height,
          :scale_x => ZOOM, 
          :scale_y => ZOOM)

          buf = Gdk::Pixbuf.new(texture.dump('rgb'), Gdk::Pixbuf::ColorSpace.new(Gdk::Pixbuf::ColorSpace::RGB), false, 8, texture.width, texture.height, texture.width * 3)
          gc = Gdk::GC.new(@graphic_box.window)
          @graphic_box.window.draw_pixbuf(gc, buf, 0, 0, 0, 0, buf.width, buf.height, Gdk::RGB::DITHER_NONE, 0, 0)
        end
      end
  end
end